﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QuantitativeInvestment.Bean;
namespace QuantitativeInvestment.Model
{
    class MoneyStrengthModel:Model
    {
        public MoneyStrengthModel()
        {
            this.name = "资金强度模型";
            Parameter p = new Parameter("观察时间", 30);
            this.paraList.Add(p.name, p);

            p = new Parameter("持有时间", 30);
            this.paraList.Add(p.name, p);



            p = new Parameter("归一化", "波动");
            p.type = "enum";
            p.enumList.Add("成交金额");
            p.enumList.Add("波动");
            this.paraList.Add(p.name, p);

            p = new Parameter("资金流出", "低");
            p.type = "enum";
            p.enumList.Add("低");
            p.enumList.Add("高");
            this.paraList.Add(p.name, p);

            p = new Parameter("选择比例", 30);
            this.paraList.Add(p.name, p);

            p = new Parameter("选择数量", 30);
            this.paraList.Add(p.name, p);
            this.factorList.Add(new Factor.MoneyStrenghFactor());
            this.factorList.Add(Factor.Factor.createFactorByName("成交金额"));
        }
        public override List<TradingStock> buy(List<TradingStock> stockList, string tradingDate)
        {
            string normalizationType = this.paraList["归一化"].value.ToString();
   
            List<TradingStock> selectedStocks = new List<TradingStock>();
            int selectPercent = Int32.Parse(this.paraList["选择比例"].value.ToString());
            int maxSelectNum = Convert.ToInt32(selectPercent * 0.01 * stockList.Count);
            int observePeriod = Int32.Parse(this.paraList["观察时间"].value.ToString());
            int currentPosition = this.container.tradingDates.IndexOf(tradingDate);
            string startDate;

            //如果超过时间范围就不返回数值
            if (currentPosition - observePeriod < 0)
                return selectedStocks;
            else
                startDate = this.container.tradingDates[currentPosition - observePeriod];

            List<TradingStock> comparedStocks = new List<TradingStock>();
            foreach (TradingStock tradingStock in stockList)
            {
                
                Stock currentStock = this.container.stocks[tradingStock.code];

                int initialStartPosition = currentStock.tradingDateList.IndexOf(currentStock.startDate);
                int stockStartPosition = currentStock.tradingDateList.IndexOf(startDate);

                int stockCurrentPosition = currentStock.tradingDateList.IndexOf(tradingDate);

                //如果之前没有数据，则跳过该个股，不作为选择
                if (stockStartPosition == -1 || stockCurrentPosition == -1)
                {

                    continue;
                }

                double[] msValues = this.container.stocks[tradingStock.code].factors["资金强度"];
                if (normalizationType == "成交金额")
                {

                    double[] amountValues = this.container.stocks[tradingStock.code].factors["成交金额"];
                    double sum= 0;
                    for (int i = stockStartPosition - initialStartPosition; i < stockCurrentPosition - initialStartPosition; i++)
                    {
                        sum += msValues[i] / amountValues[i];
                    }
                    tradingStock.comparedValue = sum;
                }
                else if (normalizationType == "波动")
                {
                    double gsms = 0;
                    double sum = 0;
                    double varianceSum = 0;
                    for (int i = stockStartPosition - initialStartPosition; i < stockCurrentPosition - initialStartPosition; i++)
                    {
                        sum += msValues[i];
                    }
                    //如果停牌，sum值为0
                    if (sum == 0)
                        gsms = 0;
                    else
                    {
                        double average = sum / (stockCurrentPosition - stockStartPosition + 1);
                        for (int i = stockStartPosition - initialStartPosition; i < stockCurrentPosition - initialStartPosition; i++)
                        {
                            varianceSum += Math.Pow((msValues[i] - average), 2);
                        }
                        gsms = sum / Math.Sqrt(varianceSum / (stockCurrentPosition - stockStartPosition));

                    }


                    tradingStock.comparedValue = gsms;
                }
              
                tradingStock.buyDate = tradingDate;
                comparedStocks.Add(tradingStock);
            }
            if (comparedStocks.Count == 0)
                return selectedStocks;
            comparedStocks = this.sort(comparedStocks);
            selectedStocks = comparedStocks.GetRange(0, maxSelectNum);
            return selectedStocks;
        }

        public override List<TradingStock> sell(List<TradingStock> stockList, string tradingDate)
        {
            int holdPeriod = Int32.Parse(this.paraList["持有时间"].value.ToString());
            int buyPosition = this.container.tradingDates.IndexOf(tradingDate);
            if (buyPosition + holdPeriod >= this.container.tradingDates.Count)
                return new List<TradingStock>();

            string sellDate = this.container.tradingDates[buyPosition + holdPeriod];
            foreach (TradingStock tradingStock in stockList)
            {
                tradingStock.sellDate = sellDate;

            }
            return stockList;
        }
    }
}
